const FUN = require('../comm/func');
const rCache = require('../model/redis_cache');
const tbDevice = require('../model/tb_device');
const dbHelp = require('../comm/db-helper');
const dataCalc = require('../comm/data-calc');
const timLib = require('../comm/time-lib');
const DB = require('../model/model_data');
const tbLog = require('../model/tb_log');
const devManger = require('../utils/devManger');
const PMR=require('../utils/policyManger');
const mbLib = require('../comm/modbus-lib');

module.exports = class Test
{
  //将数据库选项缓存到redis
  //policy 来自数据库的记录，附加了user_auth user_level字段
  //opts 数据库json字段的解析对象
  //CacheCallback 存储执行函数

  //缓存策略的db配置项到redis

  static async InitCache(policy,opts,CacheCallback)
  {
    let obj=PMR.baseParam(policy);//即将缓存到redis的参数

    //检查json选项
    if( parseInt(policy.record_limit)==0 ||
        parseInt(opts.fetch_period)==0 )
    {
      console.error('wrong template params',policy.id);
      return false;
    }

    //json options参数存储
    // obj.fetch_period = opts.fetch_period;//采样周期
    // obj.cache_expire = Number(opts.fetch_period)+60;//数据缓存reids有效期
    obj.record_limit = policy.record_limit;//数据库条数上限
    obj.data_width = opts.data_width;//数据宽度

    obj.out = '';
    obj.calc = opts.calc;//输出表达式
    for(let i=0;i<opts.calc.split(',').length;i++){obj.out+=i+',';}

    obj.master_s = opts.master_s; // 收报设备
    obj.data = opts.data; // 报文
    obj.send = opts.send||""; // 报警信息

    obj.hwtype = FUN.Hwid2TypeName(obj.master_s);
    obj.topic = '0/'+obj.hwtype+'/tx/'+obj.master_s; // 订阅主题
    obj.alarm_gap = opts.alarm_gap; // 报警间隔时间

    // 获取设备信息判断设备是否为本用户设备
    let dev = await tbDevice.find(obj.master_s);
    if(dev && dev.uid == obj.uid) obj.devPower  = 1;
    else obj.devPower  = 0;

    //数据库处理
    dbHelp.createTab(obj.table,policy.uid);
    // pcyLog(obj);
    //缓存主站参数
    obj.hwid = policy.master;
    obj.role = 'master';
    obj.brother = policy.brother;
    CacheCallback(policy.id,policy.master,obj);//记录到缓存

    //开启定时器
    // PMR.setSecInter(obj.policy_id,obj.fetch_period);
  }//end InitCache




  //modbus数据总分析
  // topic = {project,devType,func,devId}
  // dConf即InitCache中的obj
  // dataBuf即mq消息内容，buf对象
  static async DataIn(topic, dConf, dataBuf)
  {
    // pcyLog(dataBuf);
    mbLib.mbPacketParse(topic.func, dConf, dataBuf, (last,sConf)=>{
      this.dataHandler(last,sConf,dataBuf,timLib.NowStamp());
    })
  }//end function ModbusTx


  //普通的数据处理,
  static dataHandler(last,dConf,data,stamp)
  {
    //记数值
    let save=[];
    let regValArray={};
    let data_fmt=dConf.data_width.split(':');//分割数据宽度和数据格式
    if(last.opt == 0x02){
      // pcyLog('last',last);
      for(let i=0;i<last.regNum;i+=(data_fmt[0]/1))
      {
        let reg=Number(last.regStart)+i;
        let regVal=(Number(data[3+i*2])<<8)+Number(data[4+i*2]);
        if(data_fmt[0]==1)//不同字节长度得的处理
          regVal=Number(data[3+i*2]);
        if(data_fmt[0]==4)//不同字节长度得的处理
          regVal=(regVal<<16)+(Number(data[5+i*2])<<8)+Number(data[6+i*2]);
          // pcyLog('cache',data_fmt,regVal);
        if(data_fmt[1]=='f') regVal=FUN.ieee745_toFloat(regVal).toFixed(4);
        save.push({reg:reg,value:regVal,name:'#'+last.addr+':'+reg});//加入到数组
        regValArray['#'+last.addr+':'+reg]=regVal;//构建对象，暂存数据
      }
    }else if(last.opt == 0x03){
      for(let i=0;i<last.regNum;i+=(data_fmt[0]/2))
      {
        let reg=Number(last.regStart)+i;
        let regVal=(Number(data[3+i*2])<<8)+Number(data[4+i*2]);
        if(data_fmt[0]==4)//不同字节长度得的处理
          regVal=(regVal<<16)+(Number(data[5+i*2])<<8)+Number(data[6+i*2]);

        if(data_fmt[1]=='f') regVal=FUN.ieee745_toFloat(regVal).toFixed(4);
        save.push({reg:reg,value:regVal,name:'#'+last.addr+':'+reg});//加入到数组
        regValArray['#'+last.addr+':'+reg]=regVal;//构建对象，暂存数据
      }
    }

    // pcyLog('cache',save);
    // //存储寄存器值
    // rCache.setKey(PMR.rdNode(dConf),'regVal',JSON.stringify(regValArray),86400);

    dataCalc.saveOutVar(dConf,save,last.addr,stamp,(mode,fields,dArray)=>{
      if(mode=='var')
      {
        let info=[];
        fields=fields.split(',');
        for(let i=0;i<fields.length;i++) info[fields[i]]=dArray[i];//组合对象，方便处理
        info.save = save;
        this.infoJudge(dConf,info,stamp);
      }//end if mode==var
    })//end saveoutvar

  }//end funciton


  //处理单条信息的运算结果
  //info['vtag']存放序号
  //info['value']表达式结果0,1
  static infoJudge(dConf,info,stamp)
  {
    let nodeDevStamp=PMR.rdNode(dConf)+'.'+info['vtag'];
    // pcyLog(nodeDevStamp);
    let alarm_gap = dConf.alarm_gap;
    let exp=alarm_gap<3600?3600:alarm_gap;//redis最少缓存一小时

    //pcyLog('alarm',dConf.policy_id,dConf.hwid,info,info['value']?'true':'false');
    if(info['value']==1)//表达式为真
    {

        rCache.getKey(nodeDevStamp,info['vtag']).then((lastStamp)=>{//lastStamp存储的是上一次满足条件的时间

          if(lastStamp==null)//第一次满足要求
          {
            rCache.setKey(nodeDevStamp,info['vtag'],stamp,exp);
            this.alarmHandler(dConf,info,stamp);
          }
          else//之前满足过要求
          {
            let gap=(stamp-lastStamp)/1000;


            if(gap<alarm_gap)//持续时间不够长
            {
              rCache.setKey(nodeDevStamp,info['vtag'],lastStamp,exp);//刷新exprise
            }
            else//满足了要求，并且持续时间够长
            {
              rCache.setKey(nodeDevStamp,info['vtag'],stamp,exp);//刷新exprise
              this.alarmHandler(dConf,info,stamp);
            }
          }
        })
    }
    else//不满足要求
    {
      rCache.del(nodeDevStamp,info['vtag']);
    }
  }

  static alarmHandler(dConf,info,stamp){

    let id = info.vtag;
    let data = dConf.data.split(';');
    let send = dConf.send.split(';');
    let msg = "";

    // pcyLog(id,msg);

    let dArray=data[id].split(' ');
    let sendArray=[];
    for(let c of dArray)
    {
      if(c=='#c')
      {
        let crc=mbLib.crc16(sendArray);
        sendArray.push(crc>>8);
        sendArray.push(crc&0xff);
      }
      else
      {
        if(!isNaN(parseInt(c,16)))
          sendArray.push(parseInt(c,16));
      }
    }

    if(dConf.devPower == 1) {
      if(send[id]) msg = send[id];
      PMR.mqPub(dConf.topic,Buffer.from(sendArray));//发包
      tbLog.newDevLog(0,dConf.master_s,200,'['+dConf.hwid+'] ['+dConf.policy_id+'] ' + data[id] ,timLib.NowStamp());//log记录
    }else{
      // msg = '报文未发送，产品不属于该用户';
    }

    // pcyLog("11" ,msg);
    pcyLog('[%d][%d] first alarm calc[%d]', dConf.policy_id, dConf.hwid, info['vtag'], timLib.NowStr());
    if(msg) DB.addAlaramLog(dConf.uid, dConf.hwid, dConf.policy_id, info['vtag'], msg, stamp).then((id)=>{
      // PMR.alarmReport(id,dConf);
      dataCalc.dbRecordTidy(dConf.uid,dConf.table,dConf.policy_id,dConf.record_limit);
    })

  }

  //周期回调
  static SecInter(dConf,nowStamp)
  {
    let preStamp=timLib.Rounding(dConf.fetch_period,nowStamp);
    let nodeDevStamp=PMR.rdNode(dConf)+':'+preStamp;

    pcyLog('[%d] secInter timer',dConf.policy_id,timLib.NowStr());


    //返回false可结束定时器
  }



}